/* 
  Copyright (c) SilverLining 2015
  Date:    2016-1-7
  File:    Package.cpp  
  Description: 

*/

#include "stdafx.h"

using namespace System;
using namespace System::Security;
using namespace System::Threading;
using namespace System::Collections::Generic;
using namespace System::Runtime::Serialization;

#include "shim_object.h"
#include "Archiver.h"
#include "GameObject.h"
#include "Package.h"

using namespace m;
using namespace m::io;
using namespace m::alloc;

#include "BadResultException.h"

namespace SL
{
	namespace M
	{
		Package::Package()
			: _Package(nullptr)
		{
			Metadata = nullptr;
			FilesByPath = gcnew List<KeyValuePair<String^, String^>>();
			FilesByData = gcnew List<KeyValuePair<String^, array<byte>^>>();
		}

		Package::~Package()
		{
			Package::!Package();
		}

		Package::!Package()
		{
			if (_Package)
			{
				_Package->release();
			}
		}

		int Package::Result::get()
		{
			if (_Package)
			{
				return _Package->get_result();
			}
			return 0;
		}

		void Package::MakePackage()
		{
			try
			{
				if (_Package)
				{
					_Package->release();
				}
				_Package = new package();

				if (FilesByPath != nullptr)
				{
					for each (KeyValuePair<String^, String^>^ file in FilesByPath)
					{
						pin_ptr<const wchar_t> nameChars = PtrToStringChars(file->Key);
						pin_ptr<const wchar_t> fileChars = PtrToStringChars(file->Value);
						_Package->add_file(nameChars, fileChars);
					}
				}
				if (FilesByData != nullptr)
				{
					for each (KeyValuePair<String^, array<byte>^>^ file in FilesByData)
					{
						pin_ptr<const wchar_t> nameChars = PtrToStringChars(file->Key);
						array<byte>^ value = file->Value;
						pin_ptr<System::Byte> p = &value[0];
						unsigned char* pby = p;
						ref_storage track1;
						file_buffer* buffer = create(track1, new file_buffer());
						buffer->write(reinterpret_cast<char*>(pby), value->Length);
						_Package->add_file(nameChars, buffer);
					}
				}
				if (Metadata != nullptr)
				{
					_Package->set_metadata(Metadata->NativePtr);
				}
			}
			catch (bad_result_exception& bre)
			{
				throw gcnew BadResultException(&bre);
			}
		}

		void Package::ThrowIfBadResult()
		{
			if (_Package->get_result() != 0)
			{
				throw gcnew BadResultException(_Package->get_result(), "Failed to create package.");
			}
		}
	}
}